package com.lijie.ljblog.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.lijie.ljblog.mapper.PersonMapper;
import com.lijie.ljblog.model.Mail;
import com.lijie.ljblog.model.Person;
import com.lijie.ljblog.service.MailService;
import com.lijie.ljblog.service.PersonService;
import com.lijie.ljblog.service.UtilService;
import com.lijie.ljblog.util.*;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author lijie
 * @since 2021-08-28
 */
@Service
public class PersonServiceImpl extends ServiceImpl<PersonMapper, Person> implements PersonService {
    @Autowired
    PersonMapper personMapper;
    @Autowired
    QueryWrapperUtil queryWrapperUtil;
    @Resource
    UtilService utilService;
    @Resource
    RedisUtils redisUtils;
    @Autowired
    MailService mailService;
    @Autowired
    JwtUtil jwtUtil;

    @Value("${pubKey}")
    String DBpubKey;//加密存数据库
    @Value("${priKey}")
    String DBpriKey;//加密存数据库
    @Value("${web.headImg-path}")
    private String headImagePath;
    @Value("${fileUploadUrl}")
    private String headUploadPath;


    @Override
    public Result<Person> login(Person person) throws Exception{
        Result<Person> result=new Result<>();
        if(person!=null){
            if(StringUtils.isNotEmpty(person.getUserName())){
                //获取随机的私钥
                String priKey = redisUtils.get(person.getUserName());
                if(StringUtils.isNotEmpty(priKey)){
                    //redis 删去私钥
                    redisUtils.delete(person.getUserName());
                }
                //密码解密
                person.setPassword(RSAEncrypt.decrypt(person.getPassword(),priKey));;
                QueryWrapper<Person> personQueryWrapper = queryWrapperUtil.getPersonQueryWrapper(person);
                Person person1 = personMapper.selectOne(personQueryWrapper);
                if(person1!=null){
                    //私钥解码数据库的password
                    person1.setPassword(RSAEncrypt.decrypt(person1.getPassword(),DBpriKey));
                    if(person1.getPassword().equals(person.getPassword())){
                        person1.setPassword("");
                        //设置token
                        person1.setToken(jwtUtil.getToken(person1));
                        person1.setHeadImg(headUploadPath+person1.getHeadImg());
                        result.setData(person1);
                        result.setSuccess("登录成功");
                    }else{
                        result.setErrored("密码错误");
                    }
                }else{
                    result.setErrored("该用户名还未注册");
                }
            }
        }
        return result;
    }


    @Override
    public Result<Integer> getRejisterNums() throws Exception{
        Result<Integer> result=new Result<>();
        QueryWrapper<Person> queryWrapper=new QueryWrapper<>();
        Integer integer = personMapper.selectCount(queryWrapper);
        result.setData(integer);
        return result;
    }

    /**
     * 验证邮箱使用情况
     * @param person
     * @return true:没有被注册 ；false:已注册
     * @throws Exception
     */
    @Override
    public Boolean checkEmailUsed(Person person) throws Exception{
        boolean res=false;
        if(person!=null){
            List<Person> people = personMapper.selectPersonUsed(person);
            res=CollectionUtils.size(people)==0;
        }
        return res;
    }

    /**
     * @Title: emailVerification
     * @Description: (1、随机生成验证码2、上传至redis key：邮箱 value ：验证码3、将验证码发送致邮箱)
     * @Author:lijie
     * @since 2021/12/2 14:58
     * @Version:1.1.0
     */
    @Override
    public void emailVerification(String email) throws Exception {
        if(email.matches(RegexConstants.EMAIL_CHECK)){
            //随机生成验证码
            String verificationCode = getVerificationCode();
            if(StringUtils.isNotEmpty(verificationCode)){
                //上传至redis，有效时间为10分钟
                redisUtils.setEx(email,verificationCode,10, TimeUnit.MINUTES);
                //发送邮件
                Mail mail=new Mail();
                mail.setEmail(email);//收件人邮件
                Map<String,Object> map=new HashMap<>();
                map.put("username",email);//模板的数据
                map.put("code",verificationCode);//模板的验证码
                mail.setAttachment(map);
                mail.setTitle("欢迎注册 什么是快乐 个人博客");
                mailService.sendTemplateMail(mail,"mail");
            }else{
                throw new RuntimeException("验证码为空");
            }
        }else{
            throw new RuntimeException("不是正确的邮箱格式");
        }
    }

    @Override
    public Boolean personRegister(Person person) throws Exception {
        boolean res=false;
        if(person!=null){
            //对密码和邮箱解码
            String priKey = redisUtils.get(person.getUserName());
            if(StringUtils.isNotEmpty(priKey)){
                //已经获得，删去私钥。
                redisUtils.delete(person.getUserName());
            }
            String email = RSAEncrypt.decrypt(person.getEmail(), priKey);
            String password = RSAEncrypt.decrypt(person.getPassword(), priKey);
            person.setEmail(email);
            person.setPassword(password);
            //验证邮箱是正确的格式
            if(email.matches(RegexConstants.EMAIL_CHECK)){
                //验证是否被注册
                Boolean aBoolean = checkEmailUsed(person);
                if(aBoolean){
                    //验证 随机码是否一致
                    String s = redisUtils.get(person.getEmail());
                    if(StringUtils.isNotEmpty(s)&&s.equals(person.getRandomCode())){
                        //正确，注册
                        //密码邮箱二次加密
                        person.setPassword(RSAEncrypt.encrypt(person.getPassword(),DBpubKey));
//                        person.setEmail(RSAEncrypt.encrypt(person.getEmail(),DBpubKey));
                        person.setType("0");
                        int insert = personMapper.insert(person);
                        res=insert>0;
                      redisUtils.delete(person.getEmail());//已经被使用，删去该验证码。
                    }else{
                        throw new RuntimeException("验证码错误");
                    }
                }else{
                    throw new RuntimeException("该邮箱或用户名已注册");
                }
            }else{
                throw new RuntimeException("不是正确的邮箱格式");
            }
        }
        return res;
    }

    /**
     * 密码忘记验证随机码逻辑：验证随机验证码：由邮箱获得person ；修改密码。
     * @param person
     * @return
     * @throws Exception
     */
    @Override
    public Boolean forgetPassword(Person person) throws Exception {
        boolean res=false;
        if(person!=null){
            //验证邮箱是正确的格式
            if(person.getEmail().matches(RegexConstants.EMAIL_CHECK)){
                //验证是否被注册
                Boolean aBoolean = checkEmailUsed(person);
                if(!aBoolean){//未注册
                    //验证 随机码是否一致
                    String s = redisUtils.get(person.getEmail());
                    if(StringUtils.isNotEmpty(s)&&s.equals(person.getRandomCode())){
                        //正确，重置密码
                        Map<String,Object> params=new HashMap<>();
                        params.put("email",person.getEmail());
                        List<Person> peoples = personMapper.selectByMap(params);
                        if(peoples!=null&&peoples.size()==1){
                            Person user = peoples.get(0);
                            //1、密码解码
                            String priKey = redisUtils.get(person.getEmail() + "_priKey");
                            String password = RSAEncrypt.decrypt(person.getPassword(), priKey);
                            //2、密码二次加密
                            String encrypt = RSAEncrypt.encrypt(password, DBpubKey);
                            user.setPassword(encrypt);
                            //更新密码
                            int i = personMapper.updateById(user);
                            res=i==1;
                        }else {
                            throw new RuntimeException("该邮箱注册的账户不唯一，请联系我，谢谢反馈");
                        }
                        //已经被使用，删去该验证码。
                        redisUtils.delete(person.getEmail());
                    }else{
                        throw new RuntimeException("验证码错误");
                    }
                }else{
                    throw new RuntimeException("该邮箱还未注册");
                }
            }else{
                throw new RuntimeException("不是正确的邮箱格式");
            }
        }
        return res;
    }

    @Override
    public boolean headUpload(MultipartHttpServletRequest mulRequest, HttpServletRequest request) throws IOException{
        MultipartFile image = mulRequest.getFile("image");
        Integer userId =Integer.parseInt(mulRequest.getParameter("userId")) ;
        //获得图片的相对路径存入数据库
        String imagePath = utilService.fileUpload(image, headImagePath);
        Person p=new Person();
        p.setId(userId);
        p.setHeadImg(imagePath);
        int i = personMapper.updateById(p);
        return i==0;
    }

    @Override
    public Result<Person> getPerson(Person person) {
        if(person==null) {throw new RuntimeException("参数为空");}
        Result<Person> result=new Result<>();
        try{
            QueryWrapper<Person> personQueryWrapper = queryWrapperUtil.getPersonQueryWrapper(person);
            Person person1 = personMapper.selectOne(personQueryWrapper);
            person1.setHeadImg(headUploadPath+person1.getHeadImg());
            result.setData(person1);
            result.setSuccess();
        }catch (Exception e){
            result.setErrored(e.getMessage());
        }
        return result;

    }

    /**
     * 头像上传
     */


    //生成6位随机码
    private static String getVerificationCode(){
         return String.valueOf((int)((Math.random()*9+1)*Math.pow(10,5)));
    }

//    @Transactional
//    public void doEncrypt() throws Exception {
//        List<Person> peoples = personMapper.selectList(new QueryWrapper<>());
//        for(Person person:peoples){
//            String password = person.getPassword();
//            person.setPassword(RSAEncrypt.encrypt(password, DBpubKey));
//            int i = personMapper.updateById(person);
//            if(i<1){
//                throw new RuntimeException("修改错误");
//            }
//        }
//    }
}
